//
//  QRCodeViewController.swift
//  微博
//
//  Created by 段瑞金 on 16/5/12.
//  Copyright © 2016年 段瑞金. All rights reserved.
//

import UIKit
import AVFoundation

class QRCodeViewController: UIViewController {

    //连线属性
    //扫描容器
    @IBOutlet weak var containerView: UIView!
    //二维码容器高度约束
    @IBOutlet weak var codeContainerHeight: NSLayoutConstraint!
    //冲击波距离顶部的距离约束
    @IBOutlet weak var scanlineToTopConstain: NSLayoutConstraint!
    //冲击波视图
    @IBOutlet weak var scanlineView: UIImageView!
    //底部工具条
    @IBOutlet weak var bottomTabBar: UITabBar!
    
    @IBOutlet weak var QRlabel: UILabel!
    //MARK:-懒加载
    //输入设备
    private lazy var inputDevice : AVCaptureDeviceInput? = {
        let input = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
        return try? AVCaptureDeviceInput(device: input)
    }()
    //输出设备
    private lazy var outputDevice : AVCaptureMetadataOutput = {
        let output = AVCaptureMetadataOutput()
        //设置扫描的区域
        //拿到扫描容器的frame
        let containerViewFrame = self.containerView.frame
        //拿到屏幕的frame
        let screenFrame = UIScreen.mainScreen().bounds
        //计算扫描容器的x/y/height/width比例
        // 通过设置区域之后发现系统是按照右上角作为参照, 并不是以左上角
        let x = containerViewFrame.origin.x / screenFrame.size.width
        let y = containerViewFrame.origin.y / screenFrame.size.height
        let height = containerViewFrame.size.height / screenFrame.size.height
        let width = containerViewFrame.size.width / screenFrame.size.width
        output.rectOfInterest = CGRect(x: y, y: x, width: height, height: width)

        return output
    }()
    //会话
    private lazy var session = AVCaptureSession()
    //可视图层
    //如果在懒加载中用到了self,是不会有循环引用的
    private lazy var previewLayer: AVCaptureVideoPreviewLayer = {
        let layer = AVCaptureVideoPreviewLayer(session: self.session)
        return layer
    }()
    
    /// 专门用于保存描边的图层
    private lazy var containerLayer = CALayer()

    
    override func viewDidLoad() {
        super.viewDidLoad()

        //设置底部工具条上默认选中的按钮
        bottomTabBar.selectedItem = bottomTabBar.items?.first
        //监听底部工具条上按钮的点击
        bottomTabBar.delegate = self
        
        //开始扫描二维码
        setUpQRCode()
    }
    
    //界面即将显示的时候调用
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        //开始动画
        startAnimate()
        
    }
    
    
    //关闭按钮
    @IBAction func closeButton(sender: AnyObject) {
        dismissViewControllerAnimated(true, completion: nil)
    }

    //相册按钮
    @IBAction func photoButton(sender: AnyObject) {
        //判断是否可以打开指定资源
        if !UIImagePickerController.isSourceTypeAvailable(.PhotoLibrary) {
            return
        }
        //创建图片浏览器
        let picker = UIImagePickerController()
        //给图片浏览器指定数据类型
        picker.sourceType = .PhotoLibrary
        //设置代理
        picker.delegate = self
        //弹出图片浏览器
        presentViewController(picker, animated: true, completion: nil)
    }
}

//MARK:-UINavigationControllerDelegate, UIImagePickerControllerDelegate  识别图片中的二维码

extension QRCodeViewController : UINavigationControllerDelegate, UIImagePickerControllerDelegate {
    //选中一张图片时就会调用
    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
        // 1.取出选中图片
        guard let image = info[UIImagePickerControllerOriginalImage] as? UIImage else{
            return
        }
        
        guard let ciImage = CIImage(image: image) else {
            return
        }
        
        // 2.创建一个探测器
        let dict = [CIDetectorAccuracy : CIDetectorAccuracyHigh]
        let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: dict)
        
        // 3.利用探测器探测结果
        let features = detector.featuresInImage(ciImage)
        
        // 4.取出结果
        for result in features {
            print((result as! CIQRCodeFeature).messageString)
        }
        
        
        // 只要实现代理方法, 就需要我们自己手动关闭浏览器
        picker.dismissViewControllerAnimated(true, completion: nil)

    }
}


//MARK:-扫描
extension QRCodeViewController : AVCaptureMetadataOutputObjectsDelegate {
    private func setUpQRCode () ->(){
        //判断输入设备能否添加到会话中
        if !session.canAddInput(inputDevice) {
            return
        }
        //判断输出设置能否添加到会话中
        if !session.canAddOutput(outputDevice) {
            return
        }
        //将输入和输出设备添加到会话中
        session.addInput(inputDevice)
        session.addOutput(outputDevice)
        //设置输出设备能够解析的数据类型
        outputDevice.metadataObjectTypes = outputDevice.availableMetadataObjectTypes
        //设置代理,监听解析之后的数据
        
        outputDevice.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
        //设置预览界面
        previewLayer.frame = view.bounds
        view.layer.insertSublayer(previewLayer, atIndex: 0)
        
        // 7.添加专门用于保存描边图层 ,方便以后清空描边
        containerLayer.frame = view.bounds
        containerLayer.backgroundColor = UIColor.clearColor().CGColor
        view.layer.addSublayer(containerLayer)
        
        //开启扫描
        session.startRunning()
    }
    
    
    
    //MARK:-AVCaptureMetadataOutputObjectsDelegate //扫描之后会调用

    func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
        //1. 移除之前的描边
        removeSuperLayer()

        //遍历扫描返回的数据
        for objc in metadataObjects {
            let temp = objc as! AVMetadataMachineReadableCodeObject
//            RJLOG(temp)
            QRlabel.text = temp.stringValue //给界面上的label设置文字
           
            // 2. 描边
            drawCornors(objc)

       
        }
   
    }
    
    
    ///描边
    private func drawCornors (objc: AnyObject) -> (){
        //利用预览图层将corners转换为我们可识别的类型
        let  metadataObject = previewLayer.transformedMetadataObjectForMetadataObject(objc as! AVMetadataObject)
        
        //取出转换之后的corners
        let corners = (metadataObject as! AVMetadataMachineReadableCodeObject).corners
        
        //生成需要绘制的路径
        guard let path = createPath(corners) else {
            return
        }
        
        // 绘图
        let shapeLayer = CAShapeLayer()
        shapeLayer.lineWidth = 5
        shapeLayer.strokeColor = UIColor.redColor().CGColor
        shapeLayer.fillColor = UIColor.clearColor().CGColor
        shapeLayer.path = path.CGPath
        
        containerLayer.addSublayer(shapeLayer)
    }
    
    
    ///移除之前的描边
    private func removeSuperLayer () -> (){
        //每次调用这个方法的时候,青空之前的描边
        if  let subLays = containerLayer.sublayers {
            for sublay in subLays {
                
                sublay.removeFromSuperlayer()
            }
        }
    }
    
    ///生成需要绘制的路径
    private func createPath (corners: [AnyObject]?) -> UIBezierPath?{
        

        guard let array = corners /* where (array.count != 0) */ else {
            return nil
        }
        
        if array.count == 0 {
        return nil
        }
        //遍历转换的字典数组, 将字典数组中的字典转换为CGPoint
        var index = 0
        var point = CGPointZero
        // 取出数组中的每一个元素, 将取出字典转换为CGPoint
        CGPointMakeWithDictionaryRepresentation((array[index] as! CFDictionary), &point)
        index += 1
        
        //创建一个空路径
        let path = UIBezierPath()
        path.moveToPoint(point)
        
        while index < array.count {
            
            // 取出数组中的其它个元素, 将取出字典转换为CGPoint
            CGPointMakeWithDictionaryRepresentation((array[index] as! CFDictionary), &point)
            path.addLineToPoint(point)
            index += 1
        }
        path.closePath()
        
        return path

    }
   
}


//MARK:-动画代码
extension QRCodeViewController {
    //动画方法
    private func startAnimate () -> (){
        //超出容器的裁剪掉
        containerView.clipsToBounds = true
        //动画开启之前,先移除所有的动画
        scanlineView.layer.removeAllAnimations()
        //设置冲击波距离顶部的约束
        scanlineToTopConstain.constant = -codeContainerHeight.constant
        //重新布局
        view.layoutIfNeeded()
        //开启动画
        UIView.animateWithDuration(1.3) { () -> Void in
            //设置动画次数
            UIView.setAnimationRepeatCount(MAXFLOAT)
            self.scanlineToTopConstain.constant = self.codeContainerHeight.constant
            self.view.layoutIfNeeded()
        }
        
    }

}


//MARK:-底部条按钮点击监听
extension QRCodeViewController : UITabBarDelegate {
    
    func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
        //判断点击的是哪一个按钮
        if item.tag == 0 {
            //二维码
            codeContainerHeight.constant = 300
            
        }else{
            //条形码
            codeContainerHeight.constant = 150
        }
        startAnimate()
    }
}





